package top.shmly.universal.utils.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.netty.util.internal.StringUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.shmly.universal.utils.HttpRequestUtil;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * @author : zhongxianyin
 * @E-mail : music120326@hotmail.com
 * @date : 2019/4/11 9:16
 */
@SuppressWarnings("all")
public class HttpRequestUtilImpl implements HttpRequestUtil {

    @Override
    public <T> T get(Function<ServletRequestAttributes, T> attributesTFunction) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            throw new NullPointerException();
        }
        return attributesTFunction.apply(requestAttributes);
    }

    
    @Override
    public Map<String, String> getParam(HttpServletRequest request) {
        HashMap<String, String> param = new HashMap<>(30);
        param.putAll(getHeaderParam(request));
        Map<String, String> queryParam = getQueryParam(request);
        if (queryParam != null && !queryParam.isEmpty()) {
            param.putAll(queryParam);
        }
        return param;
    }
    
    @Override
    public Map<String, String> getHeaderParam(HttpServletRequest request) {
        HashMap<String, String> headerParam = new HashMap<>(15);
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String element = headerNames.nextElement();
            headerParam.put(element.toLowerCase(), request.getHeader(element));
        }
        return headerParam;
    }
    
    @Override
    public Map<String, String> getQueryParam(HttpServletRequest request) {
        String queryString = request.getQueryString();

        if (StringUtils.hasText(queryString)) {
            String[] split = queryString.split("&");
            Map<String, String> result = new HashMap<>(split.length);
            for (String s : split) {
                String[] queryParam = s.split("=");
                if (queryParam.length < 2) {
                    result.put(queryParam[0], null);
                } else {
                    result.put(queryParam[0], queryParam[1]);
                }
            }
            return result;
        }
        return null;
    }
    
    @Override
    public Map<String, String> getBodyParam(HttpServletRequest request) {
        String result = getBody(request);
        if (!StringUtil.isNullOrEmpty(result)) {
            JSONObject jsonObject = JSONUtil.parseObj(result);
            Map<String, String> resultMap = new HashMap<>();
            jsonObject.forEach((key, value) -> resultMap.put(key, value == null ? "" : value.toString()));
            return resultMap;
        }
        return null;
    }

    @Override
    public String getBody(HttpServletRequest request) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        try {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
    
    @Override
    public String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
//            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
    
    @Override
    public String jsonToGet(String body) {
        com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(body);
        StringBuilder stringBuilder = new StringBuilder();
        jsonObject.forEach((key, value) -> {
            stringBuilder.append(key);
            stringBuilder.append("=");
            stringBuilder.append(value);
            stringBuilder.append("&");
        });
        String getStr = stringBuilder.toString();
        CharSequence charSequence = getStr.subSequence(0, getStr.length() - 1);
        return "?" + charSequence.toString();
    }

    private HttpRequestUtilImpl() {
    }

    private static class SingletonHolder {
        private static final HttpRequestUtilImpl singletonInstance = new HttpRequestUtilImpl();
    }

    public static HttpRequestUtilImpl getInstance() {
        return HttpRequestUtilImpl.SingletonHolder.singletonInstance;
    }
}
